home *** CD-ROM | disk | FTP | other *** search
- /*
- * NAME
- * upload.c - 17-Apr-97 16:40:52
- *
- * AUTHOR
- * Jon Rocatis - jon@funcom.com
- *
- * DESCRIPTION
- * Yaroze Upload tool. Reads batch files and executes them.
- * Not all commands are supported at the moment!
- *
- */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <exec/types.h>
- #include <devices/serial.h>
- #include <proto/all.h>
- #include <time.h>
- #include <string.h>
-
- #include "upload_protos.h"
- #include "serial_protos.h"
- #include "tools_protos.h"
- #include "parse_protos.h"
- #include "myecoff.h"
- #include "upload.h"
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- // Endian change for 32 bit integers
- #define ENDIAN_CHG32(a) ( ((a >> 24) & 0xff) | ((a >> 8) & 0xff00) | ((a << 8) & 0x00ff0000) | ((a << 24) & 0xff000000) )
-
- // Endian change for 16 bit integers
- #define ENDIAN_CHG16(a) ( ((a >> 8) & 0xff) | ((a << 8) & 0xff00) )
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- VERSTRING; // Amiga program version string
-
- LONG jumpAddr; // The start address of the executable
-
- BOOL dontSendData;
- int baudRate;
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /*
- * NAME
- * SendGo
- *
- * FUNCTION
- * Sends the "go" command to the PlayStation. First sets the EPC register.
- *
- * INFO
- * When uploading COFF file:
- * REG_EPC must be set to a_entry
- * REG_GP must be set to a_gp
- * REG_SP must be set to 0x801fff00
- *
- */
-
- void SendGo( void )
- {
- UBYTE dynacmd[100];
- LONG cmdlen;
-
- printf( "Here we go!\n" );
- printf( "Jump address: $%08x\n\n", jumpAddr );
-
- cmdlen = sprintf( dynacmd, "sr epc %08x\015", jumpAddr);
- SerialSend( dynacmd, cmdlen );
- Wait( SIGBREAKF_CTRL_D );
- cmdlen = sprintf( dynacmd, "go\015", jumpAddr);
- SerialSend( dynacmd, cmdlen );
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /*
- * NAME
- * DataSend
- *
- * FUNCTION
- * Uploads a binary file to the PlayStation.
- *
- * INPUT
- * fh - file ptr to already opened binary file (ready to read)
- * loadAddr - the load address of the file
- * size - the size in bytes of the file
- *
- */
-
- void DataSend( const BPTR fh, const ULONG loadAddr, const ULONG size )
- {
- struct UploadHeader ulh; // Header that request file uploading on PSX
- struct Packet *packet; // Ptr to packet that is send to PSX
- ULONG sigs; // Signal mask received from Wait()
- LONG rest, // #bytes still left to be send from file
- rlen; // #bytes still left to be send from buffer
-
- static UBYTE cmd1[] = {'b','w','r',0x0d}; // "Binary Write" command
- static UBYTE cmd2[] = {0x0d};
-
- packet = AllocMem( sizeof(struct Packet), 0 );
- if ( packet == NULL )
- return;
-
- printf( "Starting upload.. " );
- fflush( stdout );
-
- SerialSend( cmd1, sizeof(cmd1) ); // Tell PSX we want to upload.. (The PSX will answer with: "bwr" 0x0a 0x0d "binary" 0x0d)
-
- //
-
- w4bin = TRUE;
- // printf( "Waiting for 'bwr binary' (with auto) \n" );
- sigs = Wait( SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D );
- w4bin = FALSE;
-
- if ( sigs & SIGBREAKF_CTRL_C )
- goto stop;
-
- if ( sigs & SIGBREAKF_CTRL_D )
- {
- // Got 'bwr binary' automatically
- Delay( 5 );
- }
-
- //
-
- packet->id = STATE_DATA;
-
- ulh.id = STATE_UPLOAD;
- ulh.address = loadAddr;
- ulh.length = size;
- SerialSend( &ulh.id, 9 ); // Tell PSX load address and size of file to upload (PSX doesn't answer this one it seems!)
-
- Delay( 20 );
-
- // Now lets send the data in 2K chunks..
-
- for ( rest = size; rest > 0; )
- {
- UBYTE chksum;
- LONG cidx;
-
- if ( rest >= BLOCKSIZE )
- rlen = BLOCKSIZE;
- else
- {
- rlen = rest;
- memset( &packet->data, 0, sizeof(packet->data) );
- }
- Read( fh, &packet->data, rlen );
-
- printf( "\r (%6d / %6d) %d%%.. ", (size - rest), size, 100 - (rest*100 / size));
- fflush( stdout );
-
- rest -= rlen;
-
- // printf( "rlen = %d, rest = %d\n", rlen, rest );
-
- for ( chksum = cidx = 0; cidx < BLOCKSIZE; cidx++ )
- chksum += packet->data[cidx];
-
- packet->chksum = chksum;
- // printf( "Chksum = %02x\n", chksum );
-
- // Wait( SIGBREAKF_CTRL_F );
- Delay(7); // 7 seems to be the lowest!
-
- retry:
- w4y = TRUE;
- SerialSend( packet, sizeof(struct Packet) );
- // printf("Waiting for 'Y' (CF)\n");
- sigs = Wait( SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F );
- if ( sigs & SIGBREAKF_CTRL_E )
- {
- // printf( "Got Y!\n");
- }
- else
- {
- if ( sigs & SIGBREAKF_CTRL_F )
- goto retry;
- else
- goto stop;
- }
- // Delay(7); // 7 seems to be the lowest!
- }
-
- printf( "\rUploaded %d bytes \n", size );
- fflush( stdout );
-
- // The whole file has been transferred! Now wait for the PSX to be ready again for more.
-
- SerialSend( cmd2, 1 );
- // printf( "Waiting for '>>'\n" );
- sigs = Wait( SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D );
- if ( sigs & SIGBREAKF_CTRL_C )
- goto stop;
- if ( sigs & SIGBREAKF_CTRL_D )
- {
- // printf( "Got >>\n" );
- }
- // printf( "\n\n" );
-
- stop:
- FreeMem( packet, sizeof(struct Packet) );
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /*
- * NAME
- * WaitForPSX
- *
- * FUNCTION
- * Waits for the PSX to send '>>'
- *
- */
-
- void WaitForPSX( void )
- {
- static UBYTE cmd2[] = {0x0d};
-
- printf( "All data transfered! (F). " );
- fflush( stdout );
- SerialSend( cmd2, 1 );
- Wait( SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_F );
- printf( "Got >>..\n\n" );
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /*
- * NAME
- * UploadExe
- *
- * FUNCTION
- * Uploads a PlayStation executable. Searches the COFF file and extracts
- * info on the 4 needed sections (text, rdata, data, sdata)
- *
- * INPUT
- * fname - ptr to filename
- *
- * RESULT
- * An uploaded file or error message if anything went wrong
- *
- */
-
- #define FAIL(a) { puts(a); goto error; }
-
- void UploadExe( char *fname )
- {
- LONG idx, totSize, numSects;
- struct Section *sections = NULL;
- struct ecoff_file_hdr header;
- struct ecoff_aout_hdr aheader;
- BPTR fh;
-
- printf( "Program load!\n" );
-
- fh = Open( fname, MODE_OLDFILE );
- if (!fh)
- FAIL( "Couldn't open file!\n" );
-
- printf( "Reading %s..\n", fname );
- Read( fh, &header, sizeof(header) );
- if ( header.f_magic != ECOFF_MIPS_MAGIC_LITTLE_SWAP )
- FAIL( "Not a Yaroze EXE file!\n" );
-
- numSects = ENDIAN_CHG16( header.f_nscns );
- sections = AllocVec( sizeof(struct Section) * numSects, 0 );
- if ( sections == NULL )
- FAIL( "Out of memory!\n" );
-
- //
-
- Read( fh, &aheader, sizeof(aheader) );
- jumpAddr = ENDIAN_CHG32( aheader.a_entry );
- printf( "Jump address: $%08x\n\n", jumpAddr );
-
- //
-
- Read( fh, sections, sizeof(struct Section) * numSects );
-
- for ( totSize = idx = 0; idx < 4 /*numSects*/; idx++ )
- {
- sections[idx].loadAddr = ENDIAN_CHG32( sections[idx].loadAddr );
- sections[idx].size = ENDIAN_CHG32( sections[idx].size );
- sections[idx].fpos = ENDIAN_CHG32( sections[idx].fpos );
- DisplaySectionInfo( §ions[idx] );
- totSize += sections[idx].size;
- }
- printf( "Total size of sections: %d bytes (%dK)\n\n", totSize, ((totSize-1) / 1024) + 1 );
-
- ///////
-
- for ( idx = 0; idx < 4; idx++ ) // Send 4 sections
- {
- Seek( fh, sections[idx].fpos, OFFSET_BEGINNING );
- DataSend( fh, sections[idx].loadAddr, sections[idx].size );
- }
- WaitForPSX();
-
- ///////
-
- error:
- if (sections) FreeVec(sections);
- if (fh) Close(fh);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- BYTE printSigNum;
-
- void main( int argc, char **argv )
- {
- char *fname;
- FILE *fp;
- // static char test[4] = {0x1,0x2,0x3,0x4};
-
- printSigNum = AllocSignal(-1);
-
- if ( (argc < 2) || (argc > 3) )
- {
- printf( "Usage: %s <batchfile> [nd]\n", argv[0] );
- exit(1);
- }
-
- fname = argv[1];
- if (!(fp = fopen( fname, "r" )))
- {
- printf( "*** Couldn't open %s!\n", fname );
- exit(1);
- }
-
- if ( argc == 3 )
- dontSendData = TRUE;
- else
- dontSendData = FALSE;
-
- baudRate = GetBaudRate();
- if (baudRate == -1)
- {
- printf( "*** Illegal baudrate!\n" );
- exit(1);
- }
-
- if ( SerialInit() )
- {
- if ( InitTask() )
- {
- LONG sigs;
-
- printf( "\nParsing '%s'. Baud rate: %d\n\n", fname, baudRate );
- ParseBatchFile( fp );
- printf( "Parsing complete. Press CTRL-F to quit\n" );
-
- Signal( task, SIGBREAKF_CTRL_E );
- do
- {
- sigs = Wait( SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D | (1L << printSigNum) );
- if (sigs & (1L << printSigNum))
- PrintLine();
- /*
- if (sigs & SIGBREAKF_CTRL_D)
- {
- printf(">> sending\n");
- SerialSend( test, 4 );
- }
- */
- } while (!(sigs & SIGBREAKF_CTRL_F));
-
- FreeTask();
- }
- else
- printf( "*** Couldn't Initialize Task!\n" );
-
- SerialClose();
- }
- else
- printf( "*** Couldn't Initialize Serial Device!\n" );
-
- fclose( fp );
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-